05|深入浅出索引(下)

索引分析

select * from T where K betwwen 3 and 5 需要执行几次树的搜索操作? ID为主键索引,K为普通索引

  • 在K的普通索引树上找到K=3对应的记录,取得对应的主键ID=300值—普通索引
  • 通过主键ID=300查到对应的记录—主键索引(回表)
  • 在K索引树取下一个值K=5,取得主键ID=500—普通索引
  • 根据ID=500取得对应的记录—主键索引(回表)
  • K索引树取下一个值k=6,不满足条件,循环结束—普通索引

这个过程总共搜索了三次普通索引,二次主键索引(回表)。如何优化索引,避免回表过程?可以使用覆盖索引

覆盖索引

select ID from T where K betwwen 3 and 5. 由于查询的返回值通过普通索引就能够获取,所以就不用回表去查主键索引了。能够减少数的搜索次数,提高查询性能。

覆盖索引的使用场景

  • 联合索引

身份证号是市民的唯一表示,而身份证号通常应该建立普通索引,如果有一个需求是通过身份证号查市民的真实姓名,可以建立身份证号和姓名的联合索引,由此可以通过直接在身份证的普通索引上直接搜索到姓名,由此可以避免回表的操作,减少语句执行时间。

最左前缀原则

B+树可以通过索引的最左前缀,来定位记录,由此可以避免为每一种查询都设计一个索引

  1. 最左前缀可以是联合索引的最左N个字段,也可以是字符串索引的最左M个字符
  • 联合索引(name,age), 如(“张三”,10),通过张三可以通过索引检索到记录,通过”张”也可以通过索引检索到记录。
  1. 如果通过调配联合索引的字段顺序来减少索引的维护?
  • 评估索引的复用能力,当已经有了(a,b)的联合索引,就不需要单独在a上面建立索引了。
  • 空间的考虑。如果已经有了(age,name)的索引,因为name的字段比age大,所以我们可以调配字段顺序(name,age),就只需要再加一个age的单字段索引。

索引下推

select * from tuser where name like “张%” and age = 10 and is ismale = 1 对于这样的查询语句,在老版本的mysql中,age和ismale没法通过最左前缀进行匹配。需要回表到主键索引进行过滤。

  • Mysql5.6之前,通过普通索引找到对应的主键,然后回到主键索引上找到对应的记录,最后去比对字段值去过滤。
  • Mysql5.6之后,Mysql进行索引下推优化,可以普通索引遍历过程中,对索引包含的字段(age)先作判断,由此在普通索引搜索过程过滤掉不满足条件的记录,减少了回表的次数。